<template>
  <view class="file-upload">
    <view class="file-upload-list">
      <view v-for="(item,index) in uploadLists" :key="index" class="item">
        <view class="video">
          <video :src="item" :controls="false" :disabled="false">
            <cover-view @click.stop="previewVideo(item)" class="video-fixed"></cover-view>
            <cover-view @click.stop="imgDel(index)" class="delete">
              <u-icon class="icon" name="close" size="30" color="#fff"></u-icon>
            </cover-view>
          </video>
        </view>
      </view>
      <view @click="chooseFile" class="item add">
        <u-icon name="plus" class="u-add-btn" size="40"></u-icon>
        <view class="tips u-m-t-20 u-font-26">选择视频</view>
      </view>
    </view>
    <view class="preview-full" v-if="previewVideoSrc">
      <video :src="previewVideoSrc" :autoplay="true" :show-fullscreen-btn="false">
        <cover-view class="close" @click="previewVideoClose">
          <u-icon class="icon" name="close" size="40" color="#333"></u-icon>
        </cover-view>
      </video>
    </view>
  </view>
</template>

<script>
export default {
  name: "file-upload",
  data() {
    return {
      uploadLists: [],
      mediaTypeData: ["image", "video", "all"],
      previewVideoSrc: "",
    };
  },
  props: {
    //展示图片/视频最大值
    max: {
      type: Number,
      default: 1,
    },
    //选择图片/视频数
    chooseNum: {
      type: Number,
      default: 9,
    },
    //发到后台的文件参数名
    name: {
      type: String,
      default: "file",
    },
    //是否展示删除按钮
    remove: {
      type: Boolean,
      default: true,
    },
    //是否展示添加按钮
    add: {
      type: Boolean,
      default: true,
    },
    //是否禁用
    disabled: {
      type: Boolean,
      default: false,
    },
    //选择照片来源 【ps：H5就别费劲了，设置了也没用。不是我说的，官方文档就这样！！！】
    sourceType: {
      type: Array,
      default: () => ["album", "camera"],
    },
    //上传地址
    action: {
      type: String,
      default: "",
    },
    //上传的请求头部
    headers: {
      type: Object,
      default: () => {},
    },
    //HTTP 请求中其他额外的 form data
    formData: {
      type: Object,
      default: () => {},
    },
    //是否需要压缩
    compress: {
      type: Boolean,
      default: true,
    },
    //压缩质量，范围0～100
    quality: {
      type: Number,
      default: 80,
    },
    //受控图片/视频列表
    value: {
      type: Array,
      default: () => [],
    },
    // 上传成功返回
    uploadSuccess: {
      default: (res) => {
        return {
          success: false,
          url: "",
        };
      },
    },
    //文件类型 image/video/all
    mediaType: {
      type: String,
      default: "image",
    },
    //拍摄视频最长拍摄时间，单位秒。最长支持 60 秒。 (只针对拍摄视频有用)
    maxDuration: {
      type: Number,
      default: 15,
    },
    //'front'、'back'，默认'back'(只针对拍摄视频有用)
    camera: {
      type: String,
      default: "back",
    },
  },
  mounted() {
    this.$nextTick(() => {
      this.uploadLists = this.value;
      if (this.mediaTypeData.indexOf(this.mediaType) == -1) {
        uni.showModal({
          title: "提示",
          content: "mediaType参数不正确",
          showCancel: false,
          success: function (res) {
            if (res.confirm) {
              //console.log('用户点击确定');
            } else if (res.cancel) {
              //console.log('用户点击取消');
            }
          },
        });
      }
    });
  },
  watch: {
    value(newVal, oldVal) {
      this.uploadLists = newVal;
    },
  },
  methods: {
    previewVideo(src) {
      this.previewVideoSrc = src;
    },
    previewVideoClose() {
      this.previewVideoSrc = "";
      console.log("previewVideoClose", this.previewVideoSrc);
    },
    imgDel(index) {
      uni.showModal({
        title: "提示",
        content: "您确定要删除么?",
        success: (res) => {
          if (res.confirm) {
            // this.uploadLists.splice(index, 1)
            // this.$emit("input", this.uploadLists);
            // this.$emit("imgDelete", this.uploadLists);
            let delUrl = this.uploadLists[index];
            this.uploadLists.splice(index, 1);
            this.$emit("input", this.uploadLists);
            this.$emit("imgDelete", {
              del: delUrl,
              tempFilePaths: this.uploadLists,
            });
          } else if (res.cancel) {
          }
        },
      });
    },
    imgPreview(index) {
      var imgData = this.uploadLists.filter((item) =>
        /.(gif|jpg|jpeg|png|gif|jpg|png)$/i.test(item)
      ); //只预览图片的
      uni.previewImage({
        urls: imgData,
        current: index,
        loop: true,
      });
    },
    chooseFile() {
      if (this.disabled) {
        return false;
      }
      switch (this.mediaTypeData.indexOf(this.mediaType)) {
        case 1: //视频
          this.videoAdd();
          break;
        case 2: //全部
          uni.showActionSheet({
            itemList: ["相册", "视频"],
            success: (res) => {
              if (res.tapIndex == 1) {
                this.videoAdd();
              } else if (res.tapIndex == 0) {
                this.imgAdd();
              }
            },
            fail: (res) => {
              console.log(res.errMsg);
            },
          });
          break;
        default:
          //图片
          this.imgAdd();
          break;
      }

      //if(this.mediaType=='image'){
    },
    videoAdd() {
      if (this.uploadLists.length) {
        return this.$u.toast("只能上传一个视频~");
      }
      // console.log("videoAdd");
      let nowNum = Math.abs(this.uploadLists.length - this.max);
      let thisNum = this.chooseNum > nowNum ? nowNum : this.chooseNum; //可选数量
      uni.chooseVideo({
        compressed: this.compress,
        sourceType: this.sourceType,
        camera: this.camera,
        maxDuration: this.maxDuration,
        success: (res) => {
          console.log("videoAdd", res);
          console.log(res.tempFilePath);
          this.chooseSuccessMethod([res.tempFilePath], 1);
          //this.imgUpload([res.tempFilePath]);
          //console.log('tempFiles', res)
          // if (this.action == '') { //未配置上传路径
          // 	this.$emit("chooseSuccess", res.tempFilePaths);
          // } else {
          // 	if (this.compress && (res.tempFiles[0].size / 1024 > 1025)) { //设置了需要压缩 并且 文件大于1M，进行压缩上传
          // 		this.imgCompress(res.tempFilePaths);
          // 	} else {
          // 		this.imgUpload(res.tempFilePaths);
          // 	}
          // }
        },
      });
    },
    imgAdd() {
      console.log("imgAdd");
      let nowNum = Math.abs(this.uploadLists.length - this.max);
      let thisNum = this.chooseNum > nowNum ? nowNum : this.chooseNum; //可选数量
      console.log("nowNum", nowNum);
      console.log("thisNum", thisNum);
      // #ifdef APP-PLUS
      if (this.sourceType.length > 1) {
        uni.showActionSheet({
          itemList: ["拍摄", "从手机相册选择"],
          success: (res) => {
            if (res.tapIndex == 1) {
              this.appGallery(thisNum);
            } else if (res.tapIndex == 0) {
              this.appCamera();
            }
          },
          fail: (res) => {
            console.log(res.errMsg);
          },
        });
      }
      if (
        this.sourceType.length == 1 &&
        this.sourceType.indexOf("album") > -1
      ) {
        this.appGallery(thisNum);
      }

      if (
        this.sourceType.length == 1 &&
        this.sourceType.indexOf("camera") > -1
      ) {
        this.appCamera();
      }
      // #endif
      //#ifndef APP-PLUS
      uni.chooseImage({
        count: thisNum,
        sizeType: ["original", "compressed"], //可以指定是原图还是压缩图，默认二者都有
        sourceType: this.sourceType,
        success: (res) => {
          this.chooseSuccessMethod(res.tempFilePaths, 0);
          //console.log('tempFiles', res)
          // if (this.action == '') { //未配置上传路径
          // 	this.$emit("chooseSuccess", res.tempFilePaths);
          // } else {
          // 	if (this.compress && (res.tempFiles[0].size / 1024 > 1025)) { //设置了需要压缩 并且 文件大于1M，进行压缩上传
          // 		this.imgCompress(res.tempFilePaths);
          // 	} else {
          // 		this.imgUpload(res.tempFilePaths);
          // 	}
          // }
        },
      });
      // #endif
    },
    appCamera() {
      var cmr = plus.camera.getCamera();
      var res = cmr.supportedImageResolutions[0];
      var fmt = cmr.supportedImageFormats[0];
      //console.log("Resolution: " + res + ", Format: " + fmt);
      cmr.captureImage(
        (path) => {
          //alert("Capture image success: " + path);
          this.chooseSuccessMethod([path], 0);
        },
        (error) => {
          //alert("Capture image failed: " + error.message);
          console.log("Capture image failed: " + error.message);
        },
        {
          resolution: res,
          format: fmt,
        }
      );
    },
    appGallery(maxNum) {
      plus.gallery.pick(
        (res) => {
          this.chooseSuccessMethod(res.files, 0);
        },
        function (e) {
          //console.log("取消选择图片");
        },
        {
          filter: "image",
          multiple: true,
          maximum: maxNum,
        }
      );
    },
    chooseSuccessMethod(filePaths, type) {
      if (this.action == "") {
        //未配置上传路径
        this.$emit("chooseSuccess", filePaths, type); //filePaths 路径 type 0 为图片 1为视频
      } else {
        if (type == 1) {
          this.imgUpload(filePaths);
        } else {
          if (this.compress) {
            //设置了需要压缩
            this.imgCompress(filePaths);
          } else {
            this.imgUpload(filePaths);
          }
        }
      }
    },
    imgCompress(tempFilePaths) {
      uni.showLoading({
        title: "压缩中...",
      });

      let compressImgs = [];
      let results = [];
      tempFilePaths.forEach((item, index) => {
        compressImgs.push(
          new Promise((resolve, reject) => {
            // #ifndef H5
            uni.compressImage({
              src: item,
              quality: this.quality,
              success: (res) => {
                //console.log('compressImage', res.tempFilePath)
                results.push(res.tempFilePath);
                resolve(res.tempFilePath);
              },
              fail: (err) => {
                //console.log(err.errMsg);
                reject(err);
              },
              complete: () => {
                //uni.hideLoading();
              },
            });
            // #endif
            // #ifdef H5
            this.canvasDataURL(
              item,
              {
                quality: this.quality / 100,
              },
              (base64Codes) => {
                //this.imgUpload(base64Codes);
                results.push(base64Codes);
                resolve(base64Codes);
              }
            );
            // #endif
          })
        );
      });
      Promise.all(compressImgs) //执行所有需请求的接口
        .then((results) => {
          uni.hideLoading();
          console.log("imgUpload", results);
          this.imgUpload(results);
        })
        .catch((res, object) => {
          uni.hideLoading();
        });
    },
    imgUpload(tempFilePaths) {
      // if (this.action == '') {
      // 	uni.showToast({
      // 		title: '未配置上传地址',
      // 		icon: 'none',
      // 		duration: 2000
      // 	});
      // 	return false;
      // }
      uni.showLoading({
        title: "上传中",
      });
      console.log("imgUpload", tempFilePaths);
      let uploadImgs = [];
      tempFilePaths.forEach((item, index) => {
        uploadImgs.push(
          new Promise((resolve, reject) => {
            console.log(index, item);
            const uploadTask = uni.uploadFile({
              url: this.action, //仅为示例，非真实的接口地址
              filePath: item,
              name: this.name,
              fileType: "image",
              formData: this.formData,
              header: this.headers,
              success: (uploadFileRes) => {
                //uni.hideLoading();
                //console.log(typeof this.uploadSuccess)
                //console.log('')
                if (typeof this.uploadSuccess == "function") {
                  if (this.uploadSuccess(uploadFileRes).success) {
                    this.value.push(this.uploadSuccess(uploadFileRes).url);
                    this.$emit("input", this.uploadLists);
                  }
                }
                resolve(uploadFileRes);
                this.$emit("uploadSuccess", uploadFileRes);
              },
              fail: (err) => {
                console.log(err);
                //uni.hideLoading();
                reject(err);
                this.$emit("uploadFail", err);
              },
              complete: () => {
                //uni.hideLoading();
              },
            });
          })
        );
      });
      Promise.all(uploadImgs) //执行所有需请求的接口
        .then((results) => {
          uni.hideLoading();
        })
        .catch((res, object) => {
          uni.hideLoading();
          this.$emit("uploadFail", res);
        });
      // uploadTask.onProgressUpdate((res) => {
      // 	//console.log('',)
      // 	uni.showLoading({
      // 		title: '上传中' + res.progress + '%'
      // 	});
      // 	if (res.progress == 100) {
      // 		uni.hideLoading();
      // 	}
      // });
    },
    canvasDataURL(path, obj, callback) {
      var img = new Image();
      img.src = path;
      img.onload = function () {
        var that = this;
        // 默认按比例压缩
        var w = that.width,
          h = that.height,
          scale = w / h;
        w = obj.width || w;
        h = obj.height || w / scale;
        var quality = 0.8; // 默认图片质量为0.8
        //生成canvas
        var canvas = document.createElement("canvas");
        var ctx = canvas.getContext("2d");
        // 创建属性节点
        var anw = document.createAttribute("width");
        anw.nodeValue = w;
        var anh = document.createAttribute("height");
        anh.nodeValue = h;
        canvas.setAttributeNode(anw);
        canvas.setAttributeNode(anh);
        ctx.drawImage(that, 0, 0, w, h);
        // 图像质量
        if (obj.quality && obj.quality <= 1 && obj.quality > 0) {
          quality = obj.quality;
        }
        // quality值越小，所绘制出的图像越模糊
        var base64 = canvas.toDataURL("image/jpeg", quality);
        // 回调函数返回base64的值
        callback(base64);
      };
    },
  },
};
</script>

<style lang="scss" scoped>
.file-upload {
  &-list {
    display: flex;
    flex-wrap: wrap;

    .item {
      width: 200rpx;
      height: 200rpx;
      margin: 10rpx;
      border-radius: 10rpx;
      position: relative;
    }

    .video {
      width: 100%;
      height: 100%;
      border-radius: 10rpx;
      position: relative;
    }

    video {
      width: 100%;
      height: 100%;
      border-radius: 10rpx;
    }

    .video-fixed {
      position: absolute;
      top: 0;
      left: 0;
      bottom: 0;
      width: 100%;
      height: 100%;
      border-radius: 10rpx;
      z-index: 996;
    }

    .delete {
      position: absolute;
      top: 10rpx;
      right: 10rpx;
      z-index: 997;
      width: 44rpx;
      height: 44rpx;
      background-color: $u-type-error;
      border-radius: 50%;
      display: flex;
      align-items: center;
      justify-content: center;

      .icon {
        z-index: 998;
      }
    }

    .add {
      background-color: #f4f5f6;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;

      .tips {
        color: #606266;
      }
    }
  }
}

.preview-full {
  position: fixed;
  top: 0;
  left: 0;
  bottom: 0;
  width: 100%;
  height: 100%;
  z-index: 1002;

  video {
    width: 100%;
    height: 100%;
    z-index: 1002;
  }

  .close {
    position: fixed;
    top: 40rpx;
    right: 40rpx;
    z-index: 1003;
    width: 80rpx;
    height: 80rpx;
    background-color: $uni-bg-color;
    border-radius: 5rpx;
    display: flex;
    align-items: center;
    justify-content: center;

    // .icon {
    //   z-index: 1004;
    // }
  }
}
</style>
